package top.hmtools.makedata.random.chineseName;

import java.util.ArrayList;
import java.util.List;

import top.hmtools.makedata.random.chineseName.Firstname;
import top.hmtools.makedata.random.chineseName.Lastname;
import top.hmtools.makedata.random.chineseName.Name;
import top.hmtools.makedata.random.chineseName.constants.FirstnameDictionary;
import top.hmtools.makedata.random.chineseName.constants.NameType;
import top.hmtools.makedata.random.chineseName.impl.ComplexFirstname;
import top.hmtools.makedata.random.chineseName.impl.ComplexLastname;
import top.hmtools.makedata.random.chineseName.impl.SingleCharacterFirstname;
import top.hmtools.makedata.random.chineseName.impl.SingleCharacterLastname;

/**
 * @Author Zhoufan [https://github.com/fantaga].
 * @Date 2016/12/26
 * @Description:名字工厂,直接被用户使用
 */
public class NamesFactory {

	private static NamesFactory instance;

	private Firstname firstname;

	public NamesFactory() {
	}

	public static NamesFactory getInstance() {
		if (instance == null) {
			instance = new NamesFactory();
		}
		return instance;
	}

	public List<String> createNames(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(0.50, 0.90, 0.50);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createGirlNames(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = null;
			name = createRandom(0.0, 0.9, 0.5);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createTwoCharsGirlNames(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(0.0, 1.0, 1.0);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createThreeCharsGirlNames(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(0.0, 1.0, 0.0);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createThreeCharsGirlNamesUseComplex(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(0.0, 0.0, 1.0);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createFourCharsGirlNamesUseComplex(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(0, 0.0, 0.0);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createBoyNames(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = null;
			name = createRandom(1.0, 0.9, 0.5);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createTwoCharsBoyNames(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(1.0, 1.0, 1.0);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createThreeCharsBoyNames(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(1.0, 1.0, 0.0);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createThreeCharsBoyNamesUseComplex(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(1.0, 0.0, 1.0);
			names.add(name.name());
		}
		return names;
	}

	public List<String> createFourCharsBoyNamesUseComplex(int size) {
		checkBounds(size);
		ArrayList<String> names = new ArrayList<String>(size);
		for (int i = 0; i < size; i++) {
			Name name = createRandom(1.0, 0.0, 0.0);
			names.add(name.name());
		}
		return names;
	}

	private void checkBounds(int size) {
		if (size <= 0)
			throw new RuntimeException("size must be a positive!");
	}

	private void checkNameLength(String firstname , int nLength){
		if (nLength < 2 || nLength > 4)
			throw new RuntimeException("名字长度2~4");
		if (firstname.length() == 1)
			if(nLength == 4)
				throw new RuntimeException("单姓姓名一般长度为2~3");
		if (firstname.length() == 2)
			if(nLength == 2)
				throw new RuntimeException("复姓姓名一般长度为3~4");
	}

	private final String createNameThroughFirstnameAndLength(String firstname,int nLength){
		final String fname = FirstnameDictionary.getFirstname(firstname);
		if(firstname.length() == 1 && nLength == 2)
			return fname + createLastName(NameType.SINGLE_LASTNAME).generate();
		if(firstname.length() == 1 && nLength == 3)
			return fname + createLastName(NameType.COMPLEX_LASTNAME).generate();
		if(firstname.length() == 2 && nLength == 3)
			return fname + createLastName(NameType.SINGLE_LASTNAME).generate();
		if(firstname.length() == 2 && nLength == 4)
			return fname + createLastName(NameType.COMPLEX_LASTNAME).generate();
		return fname + "x";
	}
	private final String createNameThroughFirstnameAndGenderAndLength(String firstname,boolean gender,int nLength){
		final String fname = FirstnameDictionary.getFirstname(firstname);
		if(firstname.length() == 1 && nLength == 2){
			return gender == true ? fname + createLastName(NameType.SINGLE_LASTNAME).generateBoyName()
					: fname + createLastName(NameType.SINGLE_FIRSTNAME).generateGirlName();
		}
		if(firstname.length() == 1 && nLength == 3) {
			return gender == true ? fname + createLastName(NameType.COMPLEX_LASTNAME).generateBoyName()
					: fname + createLastName(NameType.COMPLEX_LASTNAME).generateGirlName();
		}
		if(firstname.length() == 2 && nLength == 3) {
			return gender == true ? FirstnameDictionary.getFirstname(firstname) + createLastName(NameType.SINGLE_LASTNAME).generateBoyName()
					: fname + createLastName(NameType.SINGLE_FIRSTNAME).generateGirlName();
		}
		if(firstname.length() == 2 && nLength == 4) {
			return gender == true ? FirstnameDictionary.getFirstname(firstname) + createLastName(NameType.COMPLEX_LASTNAME).generateBoyName()
					: fname + createLastName(NameType.COMPLEX_LASTNAME).generateGirlName();
		}
		return fname + "x";
	}
	private final Name createName(boolean gender, int firstnameType, int lastnameType) {

		final Firstname firstname = createFirstName(firstnameType);
		firstname.generate();

		final Lastname lastname = createLastName(lastnameType);
		if (gender)
			lastname.generateBoyName();
		else
			lastname.generateGirlName();

		Name name = new Name(firstname, lastname);
		return name;
	}

	private final Name createRandom(double boyRatio, double singleFirstnameRatio, double singleLastnameRatio) {

		Double ratio = Math.random();
		//两字男:张三
		if (ratio < boyRatio && ratio < singleFirstnameRatio && ratio < singleLastnameRatio)
			return createName(true, NameType.SINGLE_FIRSTNAME, NameType.SINGLE_LASTNAME);
		//两字女:李丽
		if (ratio > boyRatio && ratio < singleFirstnameRatio && ratio < singleLastnameRatio)
			return createName(false, NameType.SINGLE_FIRSTNAME, NameType.SINGLE_LASTNAME);
		//复姓三字男:司马懿
		if (ratio < boyRatio && ratio > singleFirstnameRatio && ratio < singleLastnameRatio)
			return createName(true, NameType.COMPLEX_FIRSTNAME, NameType.SINGLE_LASTNAME);
		//复姓三字女:上官燕
		if (ratio > boyRatio && ratio > singleFirstnameRatio && ratio < singleLastnameRatio)
			return createName(false, NameType.COMPLEX_FIRSTNAME, NameType.SINGLE_LASTNAME);
		//三字男:李小明
		if (ratio < boyRatio && ratio < singleFirstnameRatio && ratio > singleLastnameRatio)
			return createName(true, NameType.SINGLE_FIRSTNAME, NameType.COMPLEX_LASTNAME);
		//三字女:韩梅梅
		if (ratio > boyRatio && ratio < singleFirstnameRatio && ratio > singleLastnameRatio)
			return createName(false, NameType.SINGLE_FIRSTNAME, NameType.COMPLEX_LASTNAME);
		//复姓四字男:诸葛孔明
		if (ratio < boyRatio && ratio > singleFirstnameRatio && ratio > singleLastnameRatio)
			return createName(true, NameType.COMPLEX_FIRSTNAME, NameType.COMPLEX_LASTNAME);
		//复姓四字女:易若玉瑶
		if (ratio > boyRatio && ratio > singleFirstnameRatio && ratio > singleLastnameRatio)
			return createName(false, NameType.COMPLEX_FIRSTNAME, NameType.COMPLEX_LASTNAME);
		return null;
	}

	private final Firstname createFirstName(int type) {
		return (type == NameType.SINGLE_FIRSTNAME ?
				new SingleCharacterFirstname() : new ComplexFirstname());
	}

	private final Lastname createLastName(int type) {
		return (type == NameType.SINGLE_LASTNAME ?
				new SingleCharacterLastname() : new ComplexLastname());
	}

	public String createCustomName(String firstname, int nLength) {
		checkNameLength(firstname,nLength);
		return createNameThroughFirstnameAndLength(firstname,nLength);

	}

	public List<String> createCustomNames(String firstname, int nLength, int size) {
		checkNameLength(firstname,nLength);
		checkBounds(size);
		List<String> names = new ArrayList<String>(size);
		for(int i = 0 ; i < size ; i++)
		{
			String name = createNameThroughFirstnameAndLength(firstname,nLength);
			names.add(name);
		}
		return names;
	}
	public List<String> createCustomNames(String firstname,boolean gender, int nLength, int size) {
		checkNameLength(firstname,nLength);
		checkBounds(size);
		List<String> names = new ArrayList<String>(size);
		for(int i = 0 ; i < size ; i++)
		{
			String name = createNameThroughFirstnameAndGenderAndLength(firstname,gender,nLength);
			names.add(name);
		}
		return names;
	}
}
